Saltar al contenido principal

Torneo de Drones

Esta actividad NO es un simulacro de examen. Su extensión supera lo que se solicitará en el examen de la convocatoria ordinaria. Además, en este modelo se facilita información para la autocorrección de la prueba (rúbrica detallada).

Se pretende que sirva de preparación para la prueba real ya que el formato de enunciado será similar exceptuando los detalles de la rúbrica y los elementos válidos e inválidos esperados en los sets de datos.

Contexto​

La asociación DroneLeague organiza competiciones de drones en las que participan pilotos con distintos tipos de drones. Cada piloto puede competir en varias pruebas y obtener puntos según su rendimiento.

Se deberá implementar una aplicación en Python que permita gestionar pilotos, drones, pruebas y resultados.

El sistema debe desarrollarse siguiendo los principios de la Programación Orientada a Objetos.

No se permite acceder directamente a los atributos de las clases desde fuera de ellas. Se deberán utilizar propiedades, getters, setters o métodos específicos cuando sea necesario.


Archivos entregados​

Se proporciona la siguiente estructura de proyecto. 🔗 Descargar Recursos

examen_final_python/
│
├── main.py
├── piloto.py
├── drones.py
├── torneo.py
├── carga_datos.py
│
├── data/
│ ├── pilotos.csv
│ └── pruebas.csv

El archivo main.py ya estará implementado y no se deberá modificar.

El alumnado deberá completar los archivos:

piloto.py
drones.py
torneo.py
carga_datos.py

Parte 1: Gestión de pilotos​

Modifica el fichero piloto.py para crear la clase Piloto.

Clase Piloto​

Atributos de instancia​

id_piloto
nombre
categoria
puntos
  • id_piloto: cadena de texto.
  • nombre: cadena de texto.
  • categoria: puede ser "junior", "senior" o "pro".
  • puntos: número entero. Por defecto será 0.

Restricciones​

  1. El identificador no puede estar vacío.
  2. El nombre no puede estar vacío.
  3. La categoría solo podrá tener uno de estos valores:
junior
senior
pro
  1. Los puntos no pueden ser negativos.
  2. Si se intenta asignar un valor no válido, se lanzará un ValueError.

Métodos obligatorios​

sumar_puntos(cantidad)​

Recibe una cantidad de puntos y la suma al piloto.

Reglas:

  • La cantidad debe ser un número entero.
  • La cantidad debe ser mayor que 0.
  • Si la cantidad no es válida, se lanzará un ValueError.

Métodos mágicos​

__str__​

Al imprimir un piloto, debe mostrarse:

<nombre> (<categoria>) - <puntos> puntos

Ejemplo:

Laura (senior) - 35 puntos

__eq__​

Dos pilotos se considerarán iguales si tienen el mismo id_piloto.

Ejemplo:

piloto1 == piloto2

Devolverá True si ambos pilotos tienen el mismo identificador.

__lt__​

Permitirá comparar pilotos por puntos.

piloto1 < piloto2

Devolverá True si piloto1 tiene menos puntos que piloto2.

Este método permitirá ordenar pilotos por puntuación.


Parte 2: Drones de competición​

Modifica el fichero drones.py.

Se deberá crear una clase base Drone y dos clases hijas:

DroneCarrera
DroneCarga

Clase Drone​

Atributo compartido​

Todos los drones tendrán un atributo compartido llamado:

organizacion

Su valor por defecto será:

DroneLeague

Atributos de instancia​

codigo
modelo
velocidad_maxima
autonomia
  • codigo: cadena de texto.
  • modelo: cadena de texto.
  • velocidad_maxima: número real.
  • autonomia: número entero, en minutos.

Restricciones​

  1. El código no puede estar vacío.
  2. El modelo no puede estar vacío.
  3. La velocidad máxima debe ser mayor que 0.
  4. La autonomía debe ser mayor que 0.
  5. Si se intenta asignar un valor no válido, se lanzará un ValueError.

Métodos de la clase Drone​

  • calcular_puntuacion_base()

Método polimórfico.

En la clase base debe lanzar una excepción NotImplementedError.

Método mágico​

Implementa el método mágico necesario para que, al imprimir un drone, se muestre con el siguiente formato:

<modelo> - <velocidad_maxima> km/h - <autonomia> min

Ejemplo:

Falcon X - 120.0 km/h - 18 min

Clases hijas​

Clase DroneCarrera​

Hereda de Drone.

Atributo específico

aceleracion

Será un número real mayor que 0.

Si el valor no es válido, se lanzará un ValueError.

Método calcular_puntuacion_base()

Debe calcular la puntuación base de la siguiente forma:

puntuacion = velocidad_maxima * 0.6 + aceleracion * 10

Clase DroneCarga​

Hereda de Drone.

Atributo específico

capacidad_carga

Será un número real mayor que 0.

Si el valor no es válido, se lanzará un ValueError.

Método calcular_puntuacion_base()

Debe calcular la puntuación base de la siguiente forma:

puntuacion = autonomia * 2 + capacidad_carga * 5

Parte 3: Pruebas del torneo​

Crea una clase Prueba en el fichero torneo.py.

Clase Prueba​

Atributos de instancia​

id_prueba
nombre
tipo
dificultad
participantes
  • id_prueba: cadena de texto.
  • nombre: cadena de texto.
  • tipo: puede ser "velocidad", "resistencia" o "precision".
  • dificultad: número entero entre 1 y 5.
  • participantes: lista de pilotos inscritos. Por defecto será una lista vacía.

Restricciones​

  1. El identificador no puede estar vacío.
  2. El nombre no puede estar vacío.
  3. El tipo solo podrá tener uno de estos valores:
velocidad
resistencia
precision
  1. La dificultad debe estar entre 1 y 5.
  2. Si se intenta asignar un valor no válido, se lanzará un ValueError.

Métodos obligatorios​

inscribir_piloto(piloto)​

Recibe un objeto Piloto.

Debe añadirlo a la lista de participantes.

Reglas:

  • No se puede inscribir dos veces al mismo piloto.
  • Si ya está inscrito, se lanzará un ValueError.

calcular_puntos_prueba(drone)​

Recibe un objeto de tipo Drone.

Debe calcular los puntos que se obtienen en la prueba usando esta fórmula:

puntos = int(drone.calcular_puntuacion_base() / dificultad)

Métodos mágicos​

__len__​

Debe devolver el número de pilotos inscritos en la prueba.

Ejemplo:

len(prueba)

__contains__​

Debe permitir comprobar si un piloto está inscrito en una prueba.

Ejemplo:

if piloto in prueba:
print("El piloto está inscrito")

La comparación debe hacerse usando el método __eq__ de Piloto.


Parte 4: Objeto Torneo​

Crea una clase Torneo en el fichero torneo.py.

La clase deberá gestionar pilotos, drones y pruebas.

Atributos​

pilotos
drones
pruebas
  • pilotos: diccionario donde la clave será el ID del piloto y el valor será un objeto Piloto.
  • drones: diccionario donde la clave será el código del drone y el valor será un objeto DroneCarrera o DroneCarga.
  • pruebas: diccionario donde la clave será el ID de la prueba y el valor será un objeto Prueba.

No se podrán modificar directamente estos atributos desde fuera de la clase.


Parte 5: Métodos del torneo​

La clase Torneo deberá contener los siguientes métodos.

agregar_piloto(piloto)​

Añade un piloto al torneo.

Si ya existe un piloto con el mismo ID, se lanzará un ValueError.

agregar_drone(drone)​

Añade un drone al torneo.

Si ya existe un drone con el mismo código, se lanzará un ValueError.

agregar_prueba(prueba)​

Añade una prueba al torneo.

Si ya existe una prueba con el mismo ID, se lanzará un ValueError.

inscribir_piloto_en_prueba(id_piloto, id_prueba)​

Debe inscribir un piloto en una prueba.

Reglas:

  1. El piloto debe existir.
  2. La prueba debe existir.
  3. El piloto no debe estar ya inscrito en esa prueba.

registrar_resultado(id_piloto, codigo_drone, id_prueba)​

Debe registrar el resultado de un piloto en una prueba.

Reglas:

  1. El piloto debe existir.
  2. El drone debe existir.
  3. La prueba debe existir.
  4. El piloto debe estar inscrito en la prueba.

Si se cumplen las condiciones:

  • Se calculan los puntos de la prueba.
  • Se suman al piloto.
  • Se devuelve la cantidad de puntos obtenidos.

clasificacion()​

Debe devolver una lista de pilotos ordenada de mayor a menor puntuación.

Debe utilizar la comparación definida en Piloto.

ganador()​

Debe devolver el piloto con más puntos.

Si no hay pilotos, devolverá None.

media_puntos()​

Debe devolver la media de puntos de todos los pilotos.

Si no hay pilotos, devolverá 0.

pilotos_por_categoria(categoria)​

Debe devolver una lista con los pilotos de la categoría indicada.

Si la categoría no es válida, se lanzará un ValueError.


Parte 6: Carga de datos​

Modifica el fichero carga_datos.py.

Se deberán implementar las siguientes funciones:

cargar_pilotos(torneo, path_fichero)​

Recibe:

torneo
path_fichero

Debe leer el archivo pilotos.csv, crear objetos Piloto y añadirlos al torneo.

Debe devolver el objeto torneo modificado.

Las filas incorrectas se ignorarán.

cargar_pruebas(torneo, path_fichero)​

Recibe:

torneo
path_fichero

Debe leer el archivo pruebas.csv, crear objetos Prueba y añadirlos al torneo.

Debe devolver el objeto torneo modificado.

Las filas incorrectas se ignorarán.


Parte 7: Drones de prueba para main.py​

Los drones no se cargarán desde fichero para reducir el tamaño del ejercicio.

Estos drones podrán crearse directamente en main.py para comprobar el funcionamiento:

drones_prueba = [
DroneCarrera(
codigo="D001",
modelo="Falcon X",
velocidad_maxima=120,
autonomia=18,
aceleracion=6.5
),
DroneCarrera(
codigo="D002",
modelo="Rayo Azul",
velocidad_maxima=105,
autonomia=20,
aceleracion=5.8
),
DroneCarga(
codigo="D003",
modelo="Atlas Carga",
velocidad_maxima=70,
autonomia=40,
capacidad_carga=8
),
DroneCarga(
codigo="D004",
modelo="Titan Box",
velocidad_maxima=60,
autonomia=55,
capacidad_carga=12
)
]

Datasets​

Dataset 1: pilotos.csv​

id_piloto,nombre,categoria,puntos
P001,Laura,senior,0
P002,Marcos,junior,5
P003,Sara,pro,12
P004,Diego,senior,0
P005,Nerea,pro,20
P006,Pablo,avanzado,0
P007,,junior,0
P008,Hugo,senior,-4
P009,Ana,pro,notiene
P010,Luis,junior,3

Pilotos válidos esperados​

P001
P002
P003
P004
P005
P010

Pilotos que deben ignorarse​

P006 → categoría no válida
P007 → nombre vacío
P008 → puntos negativos
P009 → puntos no numéricos

Dataset 2: pruebas.csv​

id_prueba,nombre,tipo,dificultad
PR001,Circuito rápido,velocidad,2
PR002,Vuelta larga,resistencia,3
PR003,Aterrizaje exacto,precision,4
PR004,Carrera extrema,velocidad,5
PR005,Prueba sin tipo,acrobacia,3
PR006,Dificultad baja,resistencia,0
PR007,Dificultad alta,precision,8
PR008,,velocidad,2
PR009,Desafío técnico,precision,3

Pruebas válidas esperadas​

PR001
PR002
PR003
PR004
PR009

Pruebas que deben ignorarse​

PR005 → tipo no válido
PR006 → dificultad inferior a 1
PR007 → dificultad superior a 5
PR008 → nombre vacío

Comprobaciones esperadas​

Estas comprobaciones pueden utilizarse en el main.py para verificar que el programa funciona correctamente.

Puntuaciones base de los drones​

D001 Falcon X:
120 * 0.6 + 6.5 * 10 = 72 + 65 = 137

D002 Rayo Azul:
105 * 0.6 + 5.8 * 10 = 63 + 58 = 121

D003 Atlas Carga:
40 * 2 + 8 * 5 = 80 + 40 = 120

D004 Titan Box:
55 * 2 + 12 * 5 = 110 + 60 = 170

Ejemplos de puntos por prueba​

D001 en PR001:
int(137 / 2) = 68 puntos

D004 en PR002:
int(170 / 3) = 56 puntos

D003 en PR003:
int(120 / 4) = 30 puntos

D002 en PR004:
int(121 / 5) = 24 puntos

Ejemplo de operaciones esperadas en main.py​

torneo.inscribir_piloto_en_prueba("P001", "PR001")
torneo.inscribir_piloto_en_prueba("P003", "PR002")
torneo.inscribir_piloto_en_prueba("P005", "PR003")
torneo.inscribir_piloto_en_prueba("P010", "PR004")

torneo.registrar_resultado("P001", "D001", "PR001")
torneo.registrar_resultado("P003", "D004", "PR002")
torneo.registrar_resultado("P005", "D003", "PR003")
torneo.registrar_resultado("P010", "D002", "PR004")

Resultado esperado tras esas operaciones​

Recordando que algunos pilotos ya venían con puntos iniciales:

P001 Laura:
0 + 68 = 68 puntos

P003 Sara:
12 + 56 = 68 puntos

P005 Nerea:
20 + 30 = 50 puntos

P010 Luis:
3 + 24 = 27 puntos

Comprobaciones adicionales​

ganador() → Laura o Sara

En caso de empate, devolverá el primer piloto con la máxima puntuación según la implementación del método.

media_puntos()

Deberá calcular la media con los puntos actuales de todos los pilotos cargados.

pilotos_por_categoria("pro")

Deberá devolver a Sara y Nerea.


Métodos mágicos evaluados​

Este ejercicio evalúa métodos mágicos diferentes a los modelos anteriores:

Método mágicoClaseUso
__str__PilotoRepresentación textual
__str__DroneRepresentación textual
__eq__PilotoComparar pilotos por ID
__lt__PilotoOrdenar pilotos por puntos
__len__PruebaContar participantes inscritos
__contains__PruebaComprobar si un piloto está inscrito

Rúbrica de evaluación​

Calificación total: 10 puntos​

ParteCriterioPuntuación
Parte 1Clase Piloto1,5
Parte 2Clase base Drone1,5
Parte 2Herencia y polimorfismo1,5
Parte 3Clase Prueba y métodos mágicos1,5
Parte 4Clase Torneo y lógica2
Parte 6Carga de datos CSV1
GeneralCalidad, organización y encapsulación1

Desglose detallado​

1. Clase Piloto — 1,5 puntos​

AspectoPuntos
Define correctamente los atributos indicados0,25
Valida ID, nombre, categoría y puntos0,35
Implementa correctamente sumar_puntos()0,25
Implementa correctamente __str__0,20
Implementa correctamente __eq__0,20
Implementa correctamente __lt__0,25

2. Clase base Drone — 1,5 puntos​

AspectoPuntos
Define correctamente el atributo compartido organizacion0,15
Define correctamente los atributos de instancia0,25
Valida código, modelo, velocidad y autonomía0,35
Implementa calcular_puntuacion_base() con NotImplementedError0,25
Implementa correctamente __str__0,25
Usa encapsulación básica0,25

3. Herencia y polimorfismo — 1,5 puntos​

AspectoPuntos
DroneCarrera hereda correctamente de Drone0,25
DroneCarga hereda correctamente de Drone0,25
Se inicializan correctamente los atributos de la clase padre0,25
Se validan correctamente los atributos específicos0,25
DroneCarrera calcula correctamente su puntuación base0,25
DroneCarga calcula correctamente su puntuación base0,25

4. Clase Prueba y métodos mágicos — 1,5 puntos​

AspectoPuntos
Define correctamente los atributos de Prueba0,25
Valida ID, nombre, tipo y dificultad0,25
Inscribe pilotos evitando duplicados0,25
Calcula correctamente los puntos de una prueba0,25
Implementa correctamente __len__0,25
Implementa correctamente __contains__0,25

5. Clase Torneo y lógica — 2 puntos​

AspectoPuntos
Gestiona correctamente pilotos, drones y pruebas0,30
Añade pilotos, drones y pruebas evitando duplicados0,30
Inscribe pilotos en pruebas comprobando existencia0,30
Registra resultados comprobando piloto, drone, prueba e inscripción0,45
Suma correctamente los puntos al piloto0,25
Devuelve correctamente la clasificación0,20
Devuelve correctamente ganador, media y pilotos por categoría0,20

6. Carga de datos CSV — 1 punto​

AspectoPuntos
Lee correctamente pilotos.csv0,25
Crea objetos Piloto válidos0,20
Ignora pilotos inválidos sin detener el programa0,20
Lee correctamente pruebas.csv0,20
Ignora pruebas inválidas sin detener el programa0,15

7. Calidad, organización y encapsulación — 1 punto​

AspectoPuntos
No accede directamente a atributos desde fuera de las clases0,25
Código organizado por ficheros y responsabilidades0,20
Nombres claros y coherentes0,15
Uso adecuado de excepciones0,15
Código legible y sin duplicación excesiva0,15
Respeta nombres de clases, métodos y retornos solicitados0,10

Penalizaciones generales​

SituaciónPenalización
El programa no ejecuta por errores de sintaxisHasta -3
No se usa POOHasta -4
No se implementa herenciaHasta -1,5
No se implementa polimorfismoHasta -1
No se implementan los métodos mágicos obligatoriosHasta -2
No se leen archivos externosHasta -1,5
No se respeta la estructura del proyectoHasta -1
Se accede directamente a los atributos desde fuera de las clases de forma reiteradaHasta -1
El programa se detiene ante datos erróneos del datasetHasta -1
No se respetan los nombres pedidos de clases, métodos o retornosHasta -1,5